﻿using System.Data;
using System.Security.Claims;
using Devonline.Communication.Messages;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Distributed;

namespace Devonline.Identity.Admin.Controllers;

/// <summary>
/// 用户管理
/// </summary>    
[Route("api/[controller]")]
[ApiController]
[SecurityHeaders]
[Authorize(Roles = GROUP_MAINTAINERS)]
public class UsersController : ControllerBase
{
    private readonly AdminSetting _appSetting;
    private readonly UserManager<User> _userManager;
    private readonly RoleManager<Role> _roleManager;
    private readonly UserStore _userStore;
    private readonly IdentityDbContext _context;
    private readonly IDistributedCache _cache;
    private readonly IDataService<IdentityDbContext, User> _dataService;
    private readonly ILogger<UsersController> _logger;
    private readonly IDataProtectionProvider _protector;
    private readonly IMessageCommunicator _communicator;
    private static CancellationToken CancellationToken => CancellationToken.None;

    public UsersController(
        AdminSetting appSetting,
        UserManager<User> userManager,
        RoleManager<Role> roleManager,
        UserStore userStore,
        IdentityDbContext context,
        IDataService<IdentityDbContext, User> dataService,
        IDataProtectionProvider provider,
        IMessageCommunicator communicator,
        IDistributedCache cache,
        ILogger<UsersController> logger
        )
    {
        _appSetting = appSetting;
        _userManager = userManager;
        _roleManager = roleManager;
        _userStore = userStore;
        _context = context;
        _dataService = dataService;
        _logger = logger;
        _protector = provider;
        _cache = cache;
        _communicator = communicator;
        _userManager.Logger = _logger;
    }

    #region 基础操作
    /// <summary>
    /// get user for filter
    /// </summary>
    /// <returns></returns>
    [HttpGet]
    public async Task<IActionResult> Get()
    {
        _logger.LogInformation("user {user} query the user list", User.Identity.Name);
        var select = Request.GetRequestOption<string>(QUERY_OPTION_SELECT);
        if (string.IsNullOrWhiteSpace(select) || select == CHAR_STAR.ToString() || select.ToUpperInvariant().Contains(nameof(Identity.User.PasswordHash).ToUpperInvariant()))
        {
            return BadRequest("不可查询用户敏感数据!");
        }

        var result = await _dataService.GetPagedResultAsync();
        return Ok(result);
    }
    /// <summary>
    /// 新增用户
    /// </summary>
    /// <param name="user"></param>
    /// <returns></returns>
    [HttpPost]
    public async Task<IActionResult> CreateAsync(UserViewModel viewModel)
    {
        _logger.LogInformation("user {user} will add the user {targetUser}", User.Identity.Name, viewModel);
        var user = await _userManager.FindByNameAsync(viewModel.UserName);
        if (user != null)
        {
            return BadRequest($"用户名 {viewModel.UserName} 已经存在!");
        }

        user = new User
        {
            Name = viewModel.Name,
            UserName = viewModel.UserName,
            Email = viewModel.Email,
            PhoneNumber = viewModel.PhoneNumber,
            Alias = viewModel.Alias,
            Image = viewModel.Image,
            Type = AuthorizeType.Internal,
            Description = viewModel.Description
        };

        user.Create(User.Identity.Name);
        user.Update(User.Identity.Name);
        var result = await _userManager.CreateAsync(user);
        if (result.Succeeded)
        {
            result = await _userManager.AddPasswordAsync(user, _appSetting.DefaultPassword);
            if (result.Succeeded)
            {
                _logger.LogWarning("user {user} success to add the user {targetUser} for default password", User.Identity.Name, viewModel.UserName);
            }
            else
            {
                _logger.LogWarning("user {user} success to add the user {targetUser} but no password", User.Identity.Name, viewModel.UserName);
            }

            return Ok();
        }

        var errorMessage = string.Empty;
        if (result.Errors.IsNotNullOrEmpty())
        {
            errorMessage = result.Errors.Select(x => $"{x.Code}: {x.Description}").ToString<string>();
            _logger.LogWarning("user {user} fail to add the user {targetUser}, error message is: {errorMessage}", User.Identity.Name, viewModel.UserName, errorMessage);
        }

        return BadRequest(errorMessage);
    }
    /// <summary>
    /// 新增用户的一个 Claim
    /// </summary>
    /// <param name="id"></param>
    /// <param name="claim"></param>
    /// <returns></returns>
    [HttpPut("AddClaim/{id}")]
    public async Task<ActionResult> AddClaimAsync(string id, Claim claim)
    {
        _logger.LogInformation("user {user} will add claim to user {targetUser}", User.Identity.Name, id);
        var user = await _userManager.FindByIdAsync(id);
        if (user == null)
        {
            return BadRequest($"用户 {id} 不存在!");
        }

        var result = await _userManager.AddClaimAsync(user, claim);
        if (result.Succeeded)
        {
            _logger.LogWarning("user {user} success to add claim to user {targetUser}", User.Identity.Name, user.Name);
            return Ok();
        }

        var errorMessage = string.Empty;
        if (result.Errors.IsNotNullOrEmpty())
        {
            errorMessage = result.Errors.Select(x => $"{x.Code}: {x.Description}").ToString<string>();
            _logger.LogWarning("user {user} fail to add claim to user {targetUser}, error message is: {errorMessage}", User.Identity.Name, user.Name, errorMessage);
        }

        return BadRequest(errorMessage);
    }
    /// <summary>
    /// 移除用户的一个 Claim
    /// </summary>
    /// <param name="id"></param>
    /// <param name="claim"></param>
    /// <returns></returns>
    [HttpPut("RemoveClaim/{id}")]
    public async Task<ActionResult> RemoveClaimAsync(string id, Claim claim)
    {
        _logger.LogInformation("user {user} will remove claim to user {targetUser}", User.Identity.Name, id);
        var user = await _userManager.FindByIdAsync(id);
        if (user == null)
        {
            return BadRequest($"用户 {id} 不存在!");
        }

        var result = await _userManager.RemoveClaimAsync(user, claim);
        if (result.Succeeded)
        {
            _logger.LogWarning("user {user} success to remove claim to user {targetUser}", User.Identity.Name, user.Name);
            return Ok();
        }

        var errorMessage = string.Empty;
        if (result.Errors.IsNotNullOrEmpty())
        {
            errorMessage = result.Errors.Select(x => $"{x.Code}: {x.Description}").ToString<string>();
            _logger.LogWarning("user {user} fail to remove claim to user {targetUser}, error message is: {errorMessage}", User.Identity.Name, user.Name, errorMessage);
        }

        return BadRequest(errorMessage);
    }
    /// <summary>
    /// 删除用户(逻辑删除)
    /// TBC 删除用户的时候，需要把用户的角色和权限也一起删除
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    [HttpDelete("{id}")]
    [Authorize(Roles = GROUP_MAINTAINERS)]
    public async Task<IActionResult> DeleteAsync(string id)
    {
        _logger.LogInformation("user {user} will logic delete the user {targetUser}", User.Identity.Name, id);
        var user = await _userManager.FindByIdAsync(id);
        if (user == null)
        {
            return BadRequest($"用户 {id} 不存在!");
        }

        user.State = DataState.Deleted;
        var result = await _userManager.UpdateAsync(user);
        if (result.Succeeded)
        {
            _logger.LogWarning("user {user} success to logic delete the user {targetUser}", User.Identity.Name, user.UserName);
            await RefreshUserInfo(user);
            return Ok();
        }

        var errorMessage = string.Empty;
        if (result.Errors.IsNotNullOrEmpty())
        {
            errorMessage = result.Errors.Select(x => $"{x.Code}: {x.Description}").ToString<string>();
            _logger.LogWarning("user {user} fail to logic delete the user {targetUser}, error message is: {errorMessage}", User.Identity.Name, user.UserName, errorMessage);
        }

        return BadRequest(errorMessage);
    }
    #endregion

    #region 用户敏感信息
    /// <summary>
    /// 设置用户级别
    /// </summary>
    /// <param name="viewModel"></param>
    /// <returns></returns>
    [HttpPost("SetLevel")]
    public async Task<IActionResult> SetLevelAsync(UserLevelViewModel viewModel)
    {
        _logger.LogInformation("user {user} will set user {targetUser} level to {level}", User.Identity.Name, viewModel.UserName, viewModel.LevelName);
        var user = await _userManager.FindByNameAsync(viewModel.UserName);
        if (user == null)
        {
            return BadRequest($"用户 {viewModel.UserName} 不存在!");
        }

        await _userStore.SetLevel(user, viewModel.LevelName, CancellationToken);
        user.Update(User.Identity.Name);
        var result = await _dataService.SaveChangesAsync();
        if (result >= 1)
        {
            await RefreshUserInfo(user);
            return Ok();
        }

        return BadRequest();
    }
    [HttpPost("ChangePassword")]
    public async Task<IActionResult> ChangePasswordAsync(ChangePasswordViewModel viewModel)
    {
        _logger.LogInformation("user {user} will change the password for user {targetUser}", User.Identity.Name, viewModel.UserName);
        var user = await _userManager.FindByNameAsync(viewModel.UserName);
        if (user == null)
        {
            return BadRequest($"用户 {viewModel.UserName} 不存在!");
        }

        var result = await _userManager.ChangePasswordAsync(user, viewModel.Password, viewModel.NewPassword);
        if (result.Succeeded)
        {
            _logger.LogWarning("user {user} success to change the password for user {targetUser}", User.Identity.Name, viewModel.UserName);
            return Ok();
        }

        var errorMessage = string.Empty;
        if (result.Errors.IsNotNullOrEmpty())
        {
            errorMessage = result.Errors.Select(x => $"{x.Code}: {x.Description}").ToString<string>();
            _logger.LogWarning("user {user} fail to change the password for user {targetUser}, error message is: {errorMessage}", User.Identity.Name, viewModel.UserName, errorMessage);
        }

        return BadRequest(errorMessage);
    }
    [HttpPost("ResetPassword")]
    [Authorize(Roles = GROUP_MAINTAINERS)]
    public async Task<IActionResult> ResetPasswordAsync(ResetPasswordViewModel viewModel)
    {
        _logger.LogInformation("user {user} will reset the password user {targetUser}", User.Identity.Name, viewModel.UserName);
        var user = await _userManager.FindByNameAsync(viewModel.UserName);
        if (user == null)
        {
            return BadRequest($"用户 {viewModel.UserName} 不存在!");
        }

        var result = await _userManager.ResetPasswordAsync(user, viewModel.Token, viewModel.Password);

        if (result.Succeeded)
        {
            _logger.LogWarning("user {user} success to reset the password for user {targetUser}", User.Identity.Name, viewModel.UserName);
            return Ok();
        }

        var errorMessage = string.Empty;
        if (result.Errors.IsNotNullOrEmpty())
        {
            errorMessage = result.Errors.Select(x => $"{x.Code}: {x.Description}").ToString<string>();
            _logger.LogWarning("user {user} fail to reset the password for user {targetUser}, error message is: {errorMessage}", User.Identity.Name, viewModel.UserName, errorMessage);
        }

        return BadRequest(errorMessage);
    }
    [HttpPost("ChangePhoneNumber")]
    public async Task<IActionResult> ChangePhoneNumberAsync(ChangePhoneNumberViewModel viewModel)
    {
        _logger.LogInformation("user {user} will change the phone number for user {targetUser}", User.Identity.Name, viewModel.UserName);
        var user = await _userManager.FindByNameAsync(viewModel.UserName);
        if (user == null)
        {
            return BadRequest($"用户 {viewModel.UserName} 不存在!");
        }

        var result = await _userManager.ChangePhoneNumberAsync(user, viewModel.PhoneNumber, viewModel.Token);
        if (result.Succeeded)
        {
            _logger.LogWarning("user {user} success to change the phone number for user {targetUser}", User.Identity.Name, viewModel.UserName);
            return Ok();
        }

        var errorMessage = string.Empty;
        if (result.Errors.IsNotNullOrEmpty())
        {
            errorMessage = result.Errors.Select(x => $"{x.Code}: {x.Description}").ToString<string>();
            _logger.LogWarning("user {user} fail to change the phone number for user {targetUser}, error message is: {errorMessage}", User.Identity.Name, viewModel.UserName, errorMessage);
        }

        return BadRequest(errorMessage);
    }
    [HttpPost("ChangeEmail")]
    public async Task<IActionResult> ChangeEmailAsync(ChangeEmailViewModel viewModel)
    {
        _logger.LogInformation("user {user} will change the email for user {targetUser}", User.Identity.Name, viewModel.UserName);
        var user = await _userManager.FindByNameAsync(viewModel.UserName);
        if (user == null)
        {
            return BadRequest($"用户 {viewModel.UserName} 不存在!");
        }

        var result = await _userManager.ChangeEmailAsync(user, viewModel.Email, viewModel.Token);
        if (result.Succeeded)
        {
            _logger.LogWarning("user {user} success to change the email for user {targetUser}", User.Identity.Name, viewModel.UserName);
            return Ok();
        }

        var errorMessage = string.Empty;
        if (result.Errors.IsNotNullOrEmpty())
        {
            errorMessage = result.Errors.Select(x => $"{x.Code}: {x.Description}").ToString<string>();
            _logger.LogWarning("user {user} fail to change the email for user {targetUser}, error message is: {errorMessage}", User.Identity.Name, viewModel.UserName, errorMessage);
        }

        return BadRequest(errorMessage);
    }
    #endregion

    #region 用户角色
    /// <summary>
    /// 获取用户角色列表
    /// </summary>
    /// <param name="userName"></param>
    /// <returns></returns>
    [HttpGet("GetUserRoles/{userName}")]
    public async Task<ActionResult> GetUserRolesAsync(string userName)
    {
        _logger.LogInformation("user {user} will query user {targetUser} roles", User.Identity.Name, userName);
        var user = await _userManager.FindByNameAsync(userName);
        if (user == null)
        {
            return BadRequest($"用户 {userName} 不存在!");
        }

        return Ok(await _userManager.GetRolesAsync(user));
    }
    /// <summary>
    /// 获取某个角色的用户列表
    /// </summary>
    /// <param name="roleName"></param>
    /// <returns></returns>
    [HttpGet("GetRoleUsers/{roleName}")]
    public async Task<IActionResult> GetRoleUsersAsync(string roleName)
    {
        _logger.LogInformation("user {user} will query role {role} users", User.Identity.Name, roleName);
        if (!await _roleManager.RoleExistsAsync(roleName))
        {
            return BadRequest($"角色 {roleName} 不存在!");
        }

        return Ok(await _userManager.GetUsersInRoleAsync(roleName));
    }
    /// <summary>
    /// 将用户添加到角色
    /// </summary>
    /// <param name="userName"></param>
    /// <param name="role"></param>
    /// <returns></returns>
    [HttpPost("AddUserToRole")]
    public async Task<IActionResult> AddUserToRoleAsync(UserRoleViewModel viewModel)
    {
        _logger.LogInformation("user {user} will assign user {targetUser} to role {role}", User.Identity.Name, viewModel.UserName, viewModel.RoleName);
        var user = await _userManager.FindByNameAsync(viewModel.UserName);
        if (user == null)
        {
            return BadRequest($"用户 {viewModel.UserName} 不存在!");
        }

        var result = await _userManager.AddToRoleAsync(user, viewModel.RoleName);
        if (result.Succeeded)
        {
            _logger.LogWarning("user {user} success assign user {targetUser} to role {role}", User.Identity.Name, viewModel.UserName, viewModel.RoleName);
            await RefreshUserInfo(user);
            return Ok();
        }

        var errorMessage = string.Empty;
        if (result.Errors.IsNotNullOrEmpty())
        {
            errorMessage = result.Errors.Select(x => $"{x.Code}: {x.Description}").ToString<string>();
            _logger.LogWarning("user {user} fail assign user {targetUser} to role {role}, error message is: {errorMessage}", User.Identity.Name, viewModel.UserName, viewModel.RoleName, errorMessage);
        }

        return BadRequest(errorMessage);
    }
    /// <summary>
    /// 从角色中移除用户(物理删除)
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    [HttpPost("RemoveUserFromRole")]
    public async Task<IActionResult> RemoveUserFromRoleAsync(UserRoleViewModel viewModel)
    {
        _logger.LogInformation("user {user} will remove user {targetUser} from role {role}", User.Identity.Name, viewModel.UserName, viewModel.RoleName);
        var user = await _userManager.FindByNameAsync(viewModel.UserName);
        if (user == null)
        {
            return BadRequest($"用户 {viewModel.UserName} 不存在!");
        }

        var result = await _userManager.RemoveFromRoleAsync(user, viewModel.RoleName);
        if (result.Succeeded)
        {
            _logger.LogWarning("user {user} success remove user {targetUser} from role {role}", User.Identity.Name, viewModel.UserName, viewModel.RoleName);
            await RefreshUserInfo(user);
            return Ok();
        }

        var errorMessage = string.Empty;
        if (result.Errors.IsNotNullOrEmpty())
        {
            errorMessage = result.Errors.Select(x => $"{x.Code}: {x.Description}").ToString<string>();
            _logger.LogWarning("user {user} fail remove user {targetUser} from role {role}, error message is: {errorMessage}", User.Identity.Name, viewModel.UserName, viewModel.RoleName, errorMessage);
        }

        return BadRequest(errorMessage);
    }
    /// <summary>
    /// 更新用户角色
    /// </summary>
    /// <param name="userName"></param>
    /// <param name="roles"></param>
    /// <returns></returns>
    [HttpPost("ChangeUserRoles/{userName}")]
    public async Task<IActionResult> ChangeUserRolesAsync(string userName, List<string> roles)
    {
        roles ??= new List<string>();
        var roleNames = roles.ToString<string>();
        _logger.LogInformation("user {user} will assign user {targetUser} to roles {roles}", User.Identity.Name, userName, roleNames);
        var user = await _userManager.FindByNameAsync(userName);
        if (user == null)
        {
            return BadRequest($"用户 {userName} 不存在!");
        }

        var exists = await _userManager.GetRolesAsync(user);
        var adds = roles.Except(exists);
        var removes = exists.Except(roles);

        IdentityResult result = IdentityResult.Success;
        if (removes.IsNotNullOrEmpty())
        {
            result = await _userManager.RemoveFromRolesAsync(user, removes);
        }

        if (result.Succeeded)
        {
            _logger.LogWarning("user {user} success remove user {targetUser} from roles {roles}", User.Identity.Name, userName, removes.ToString<string>());
            if (adds.IsNotNullOrEmpty())
            {
                result = await _userManager.AddToRolesAsync(user, adds);
            }

            if (result.Succeeded)
            {
                _logger.LogWarning("user {user} success assign user {targetUser} to roles {roles}", User.Identity.Name, userName, adds.ToString<string>());
                await RefreshUserInfo(user);
                return Ok();
            }
        }

        var errorMessage = string.Empty;
        if (result.Errors.IsNotNullOrEmpty())
        {
            errorMessage = result.Errors.Select(x => $"{x.Code}: {x.Description}").ToString<string>();
            _logger.LogWarning("user {user} fail to change user {targetUser} roles {roles}, error message is: {errorMessage}", User.Identity.Name, userName, roleNames, errorMessage);
        }

        return BadRequest(errorMessage);
    }
    #endregion

    #region 用户组
    /// <summary>
    /// 获取用户所在组列表, 返回组名称字符串数组
    /// </summary>
    /// <param name="userName"></param>
    /// <returns></returns>
    [HttpGet("GetUserGroups/{userName}")]
    public async Task<ActionResult> GetUserGroupsAsync(string userName)
    {
        _logger.LogInformation("user {user} will query user {targetUser} groups", User.Identity.Name, userName);
        var user = await _userManager.FindByNameAsync(userName);
        if (user == null)
        {
            return BadRequest($"用户 {userName} 不存在!");
        }

        return Ok(await _userStore.GetUserGroupsAsync(user, CancellationToken));
    }
    /// <summary>
    /// 获取组用户列表, 返回用户列表
    /// TODO TBC 目前没有分页, 此处需要返回分页结果
    /// </summary>
    /// <param name="groupName"></param>
    /// <returns></returns>
    [HttpGet("GetGroupUsers/{groupName}")]
    public async Task<IActionResult> GetGroupUsersAsync(string groupName)
    {
        _logger.LogInformation("user {user} will query group {group} users", User.Identity.Name, groupName);
        if (!await _roleManager.RoleExistsAsync(groupName))
        {
            return BadRequest($"用户组 {groupName} 不存在!");
        }

        var users = await _userStore.GetGroupUsersAsync(groupName, CancellationToken);
        if (users.IsNotNullOrEmpty())
        {
            var result = users.Select(x => new UserListModel
            {
                Id = x.Id,
                UserName = x.UserName,
                Alias = x.Alias,
                Description = x.Description,
                Email = x.Email,
                Image = x.Image,
                Name = x.Name,
                PhoneNumber = x.PhoneNumber,
                State = x.State
            }).ToList();

            return Ok(new PagedResult { Rows = result });
        }

        return Ok();
    }
    /// <summary>
    /// 将用户添加到组
    /// </summary>
    /// <param name="viewModel"></param>
    /// <returns></returns>
    [HttpPost("AddUserToGroup")]
    public async Task<IActionResult> AddUserToGroupAsync(UserGroupViewModel viewModel)
    {
        _logger.LogInformation("user {user} will assign user {targetUser} to group {group}", User.Identity.Name, viewModel.UserName, viewModel.GroupName);
        var user = await _userManager.FindByNameAsync(viewModel.UserName);
        if (user == null)
        {
            return BadRequest($"用户 {viewModel.UserName} 不存在!");
        }

        var result = await _userStore.AddToGroupAsync(user, viewModel.GroupName, CancellationToken);
        if (result.Succeeded)
        {
            _logger.LogWarning("user {user} success assign user {targetUser} to group {group}", User.Identity.Name, viewModel.UserName, viewModel.GroupName);
            await RefreshUserInfo(user);
            return Ok();
        }

        var errorMessage = string.Empty;
        if (result.Errors.IsNotNullOrEmpty())
        {
            errorMessage = result.Errors.Select(x => $"{x.Code}: {x.Description}").ToString<string>();
            _logger.LogWarning("user {user} fail assign user {targetUser} to group {group}, error message is: {errorMessage}", User.Identity.Name, viewModel.UserName, viewModel.GroupName, errorMessage);
        }

        return BadRequest(errorMessage);
    }
    /// <summary>
    /// 从组中移除用户(物理删除)
    /// </summary>
    /// <param name="viewModel"></param>
    /// <returns></returns>
    [HttpPost("RemoveUserFromGroup")]
    public async Task<IActionResult> RemoveUserFromGroupAsync(UserGroupViewModel viewModel)
    {
        _logger.LogInformation("user {user} will remove user {targetUser} from group {group}", User.Identity.Name, viewModel.UserName, viewModel.GroupName);
        var user = await _userManager.FindByNameAsync(viewModel.UserName);
        if (user == null)
        {
            return BadRequest($"用户 {viewModel.UserName} 不存在!");
        }

        var result = await _userStore.RemoveFromGroupAsync(user, viewModel.GroupName, CancellationToken);
        if (result.Succeeded)
        {
            _logger.LogWarning("user {user} success remove user {targetUser} from group {group}", User.Identity.Name, viewModel.UserName, viewModel.GroupName);
            await RefreshUserInfo(user);
            return Ok();
        }

        var errorMessage = string.Empty;
        if (result.Errors.IsNotNullOrEmpty())
        {
            errorMessage = result.Errors.Select(x => $"{x.Code}: {x.Description}").ToString<string>();
            _logger.LogWarning("user {user} fail remove user {targetUser} from group {group}, error message is: {errorMessage}", User.Identity.Name, viewModel.UserName, viewModel.GroupName, errorMessage);
        }

        return BadRequest(errorMessage);
    }
    /// <summary>
    /// 更新用户组织单位
    /// </summary>
    /// <param name="userName"></param>
    /// <param name="groups"></param>
    /// <returns></returns>
    [HttpPost("ChangeUserGroups/{userName}")]
    public async Task<IActionResult> ChangeUserGroupsAsync(string userName, List<string> groups)
    {
        groups ??= new List<string>();
        var groupNames = groups.ToString<string>();
        _logger.LogInformation("user {user} will assign user {targetUser} to groups {groups}", User.Identity.Name, userName, groupNames);
        var user = await _userManager.FindByNameAsync(userName);
        if (user == null)
        {
            return BadRequest($"用户 {userName} 不存在!");
        }

        var exists = await _userStore.GetUserGroupsAsync(user);
        var adds = groups.Except(exists);
        var removes = exists.Except(groups);

        IdentityResult result = IdentityResult.Success;
        if (removes.IsNotNullOrEmpty())
        {
            result = await _userStore.RemoveFromGroupsAsync(user, removes);
        }

        if (result.Succeeded)
        {
            _logger.LogWarning("user {user} success remove user {targetUser} from groups {groups}", User.Identity.Name, userName, removes.ToString<string>());
            if (adds.IsNotNullOrEmpty())
            {
                result = await _userStore.AddToGroupsAsync(user, adds);
            }

            if (result.Succeeded)
            {
                _logger.LogWarning("user {user} success assign user {targetUser} to groups {groups}", User.Identity.Name, userName, adds.ToString<string>());
                await RefreshUserInfo(user);
                return Ok();
            }
        }

        var errorMessage = string.Empty;
        if (result.Errors.IsNotNullOrEmpty())
        {
            errorMessage = result.Errors.Select(x => $"{x.Code}: {x.Description}").ToString<string>();
            _logger.LogWarning("user {user} fail to change user {targetUser} groups {groups}, error message is: {errorMessage}", User.Identity.Name, userName, groupNames, errorMessage);
        }

        return BadRequest(errorMessage);
    }
    #endregion

    #region 内部方法
    /// <summary>
    /// 更新用户授权相关缓存
    /// </summary>
    /// <returns></returns>
    private async Task RefreshUserInfo(User user)
    {
        //更新用户授权相关缓存
        await _context.GetUserAccessResourcesAsync(_cache, user.UserName, true);

        //强制推送客户端更新
        await _communicator.SendAsync(Constants.CACHE_USER_INFO, user.UserName, MessageType.Cache);
    }
    #endregion
}